//
//  TLEngine.m
//  WebViewPreload
//
//  Created by Tianlong on 2018/2/17.
//  Copyright © 2018年 tianlong. All rights reserved.
//

#import "TLEngine.h"

static NSMutableArray *customRequestClassArray = nil;
static NSLock *sonicRequestClassLock;

@interface TLEngine ()<TLConnectionDelegate>
@property (strong, nonatomic) NSOperationQueue *delegateQueue;
@property (strong, nonatomic) NSMutableURLRequest *request;
@property (strong, nonatomic) NSHTTPURLResponse *response;
@property (strong, nonatomic) NSError *error;
@property (strong, nonatomic) TLConnection *connection;
@end

@implementation TLEngine

- (instancetype)initWithUrl:(NSString *)url delegate:(id<TLEngineDelegate>) delegate delegateQueue:(NSOperationQueue *) queue
{
    if (self == [super init]) {
        self.delegate = delegate;
        self.delegateQueue = queue;
        _request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    }
    return self;
}

- (void)dealloc
{
    if (nil != self.connection) {
        [self.connection stopLoading];
        _connection = nil;
    }
    
    if (nil != _request) {
        _request = nil;
    }
    
    if (nil != _response) {
        _request = nil;
    }
    
    if (nil != _error) {
        _error = nil;
    }
}

#pragma mark - NSStringEncoding
- (NSStringEncoding)encodingFromHeaders
{
    NSString *contentType = [[self responseHeaderForKey:[HTTPHeaderKeyContentType lowercaseString]] lowercaseString];
    if ([contentType containsString:@"charset="]) {
        NSRange charsetRange = [contentType rangeOfString:@"charset="];
        NSString *charsetString = [contentType substringFromIndex: charsetRange.location + charsetRange.length];
        if ([charsetString containsString:@";"] || [charsetString containsString:@" "]) {
            charsetString = [charsetString substringToIndex:charsetString.length - 1];
        }
        NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef) charsetString));
        if (kCFStringEncodingInvalidId != encoding) {
            return encoding;
        }
    }
    return NSUTF8StringEncoding;
}

- (NSString *)responseHeaderForKey:(NSString *)aKey
{
    NSString *header = nil;
    if (_response) {
        header = [_response.allHeaderFields objectForKey:[aKey lowercaseString]];
    }
    return header;
}

#pragma mark -  开启请求 / 停止请求
- (void)start
{
    if (nil == self.connection) {
        Class customRequest = [self canCustomRequest];
        if (!customRequest) {
            customRequest = [TLConnection class];
        }
        TLConnection *tConnect = [[customRequest alloc]initWithRequest:self.request delegate: self delegateQueue:self.delegateQueue];
        self.connection = tConnect;
        [self.connection startLoading];
    }
}

- (void)stop
{
    self.delegateQueue = nil;
    self.delegate = nil;
    
    if (self.connection) {
        [self.connection stopLoading];
    } else {
        NSLog(@"SonicServer.stop warning:Request headers should be set only before server start!");
    }
}

#pragma mark - TLConnectionDelegate
- (void)connection:(TLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response{
    NSLog(@"%s",__func__);
    if ([self.delegate respondsToSelector:@selector(engine:didReceiveData:)]) {
        [self.delegate engine:self didRecieveResponse:response];
    }
}

- (void)connection:(TLConnection *)connection didReceiveData:(NSData *)data{
    NSLog(@"%s",__func__);
    
    if (nil == _responseData) {
        _responseData = [NSMutableData data];
    }
    NSData *copyData = [data copy];
    [self.responseData appendData:copyData];
    
    if ([self.delegate respondsToSelector:@selector(engine:didReceiveData:)]) {
        [self.delegate engine:self didReceiveData:data];
    }
}

- (void)connection:(TLConnection *)connection didCompleteWithError:(NSError *)error{
    NSLog(@"%s",__func__);
    
    if ([self.delegate respondsToSelector:@selector(engine:didCompleteWithError:)]) {
        [self.delegate engine:self didCompleteWithError:error];
    }
}

- (void)connectionDidCompleteWithoutError:(TLConnection *)connection{
    NSLog(@"%s",__func__);
    
    _htmlString = [[NSString alloc]initWithData:self.responseData encoding:[self encodingFromHeaders]];
    TLLog(@"connectionDidCompleteWithoutError_htmlString = %@",_htmlString);
    
    if ([self.delegate respondsToSelector:@selector(engineDidCompleteWithoutError:)]) {
        [self.delegate engineDidCompleteWithoutError:self];
    }
}


/** 自定义Request */
- (Class)canCustomRequest
{
    Class findDestClass = nil;
    
    for (NSInteger index = customRequestClassArray.count - 1; index >= 0; index--) {
        
        Class itemClass = customRequestClassArray[index];
        
        NSMethodSignature *sign = [itemClass methodSignatureForSelector:@selector(canInitWithRequest:)];
        NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:sign];
        invoke.target = itemClass;
        NSURLRequest *argRequest = self.request;
        [invoke setArgument:&argRequest atIndex:2];
        invoke.selector = @selector(canInitWithRequest:);
        [invoke invoke];
        
        BOOL canCustomRequest;
        [invoke getReturnValue:&canCustomRequest];
        
        if (canCustomRequest) {
            findDestClass = itemClass;
            break;
        }
    }
    
    return findDestClass;
}


@end
